package com.sprouting.ops.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sprouting.ops.dao.*;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.model.*;
import com.sprouting.ops.model.qo.ComputerServerAllQo;
import com.sprouting.ops.model.qo.OpsComputerServerQo;
import com.sprouting.ops.model.vo.DeployPortVo;
import com.sprouting.ops.model.vo.OpsComputerServerVo;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务器与计算机信息表
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2023/11/8 16:34
 */
@Service
@Slf4j
public class OpsComputerServerService extends ServiceImpl<OpsComputerServerDao, OpsComputerServer> {

    @Resource
    private OpsComputerServerDao opsComputerServerDao;
    @Resource
    private DromaraFileStorageDao dromaraFileStorageDao;
    @Resource
    private OpsComputerFileDao opsComputerFileDao;
    @Resource
    private OpsDeployToolDao opsDeployToolDao;
    @Resource
    private OpsDeployDao opsDeployDao;
    @Resource
    private OpsDeployLinkDao opsDeployLinkDao;


    /**
     * 分页查询 服务器与计算机信息
     * @param page 分页参数
     * @param query 查询参数
     * @return
     */
    public Page<OpsComputerServerVo> getComputerServerPageList(Page page, OpsComputerServerQo query) {
        return opsComputerServerDao.getComputerServerPageList(page, query);
    }

    /**
     * 根据场所ID获取服务器数量
     * @param siteId 场所ID
     * @return
     */
    public long getCountBySiteId(String siteId) {
        return opsComputerServerDao.getCountBySiteId(siteId);
    }

    /**
     * 检查IP地址是否已经在场所存在
     * @param id 忽略的ID
     * @param siteId 场所ID
     * @param ip 要验证的IP地址
     * @return
     */
    public OpsComputerServer getBySiteAndIpFilterId(String id, String siteId, String ip) {
        return opsComputerServerDao.getBySiteAndIpFilterId(id, siteId, ip);
    }

    /**
     * 找到下级
     * @param id 上级节点
     * @return
     */
    public List<OpsComputerServerVo> getSonNode(String id) {
        return opsComputerServerDao.getSonNode(id);
    }

    /**
     * 找到指定id下的所有子级
     * @param parentId 父级ID
     * @return
     */
    public List<OpsComputerServerVo> getSonByParentId(String parentId) {
        return opsComputerServerDao.getSonByParentId(parentId);
    }

    /**
     * 根据场所ID查询计算机信息
     * @param siteId 场所ID
     * @return
     */
    public List<OpsComputerServerVo> getBySiteId(String siteId) {
        return opsComputerServerDao.getBySiteId(siteId);
    }

    /**
     * 保存计算机
     * @param opsComputerServer 计算机
     * @param dromaraFileStorageList 访问登录信息的Markdown
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveComputerServer(OpsComputerServer opsComputerServer, List<DromaraFileStorage> dromaraFileStorageList) {
        opsComputerServerDao.insert(opsComputerServer);
        if (CollUtil.isNotEmpty(dromaraFileStorageList)){
            for (DromaraFileStorage dromaraFileStorage : dromaraFileStorageList) {
                dromaraFileStorageDao.updateById(dromaraFileStorage);
            }
        }
    }

    /**
     * 更新一个服务器或计算机
     * @param opsComputerServer 计算机
     * @param dromaraFileStorageList 访问登录信息的Markdown
     */
    @Transactional(rollbackFor = Exception.class)
    public void updComputerServer(OpsComputerServer opsComputerServer, List<DromaraFileStorage> dromaraFileStorageList) {
        opsComputerServerDao.updateById(opsComputerServer);
        if (CollUtil.isNotEmpty(dromaraFileStorageList)){
            for (DromaraFileStorage dromaraFileStorage : dromaraFileStorageList) {
                dromaraFileStorageDao.updateById(dromaraFileStorage);
            }
        }
    }

    /**
     * 删除一个 服务器或计算机
     * @param computerServer 计算机
     * @param accessList 登录信息中的授权访问信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void delComputerServer(OpsComputerServer computerServer, List<DromaraFileStorage> accessList) {
        opsComputerServerDao.deleteById(computerServer);

        if (CollUtil.isNotEmpty(accessList)){
            for (DromaraFileStorage dromaraFileStorage : accessList) {
                dromaraFileStorage.setTempFile(ConstantBase.TempFile.PRODUCTION_DEL);
                dromaraFileStorage.setDelTime(new Date());
                dromaraFileStorageDao.updateById(dromaraFileStorage);
            }
        }

        // 删除文件树
        LambdaUpdateWrapper<OpsComputerFile> wrapperComputerFile = new LambdaUpdateWrapper<>();
        wrapperComputerFile.eq(OpsComputerFile::getComputerServerId, computerServer.getId());
        opsComputerFileDao.delete(wrapperComputerFile);

        // 删除绑定的工具
        LambdaUpdateWrapper<OpsDeployTool> wrapperDeployTool = new LambdaUpdateWrapper<>();
        wrapperDeployTool.eq(OpsDeployTool::getComputerServerId, computerServer.getId());
        opsDeployToolDao.delete(wrapperDeployTool);

        // 删除绑定的组件
        List<OpsDeploy> deployList = opsDeployDao.getByComputerServerId(computerServer.getId());
        LambdaUpdateWrapper<OpsDeploy> wrapperDeploy = new LambdaUpdateWrapper<>();
        wrapperDeploy.eq(OpsDeploy::getComputerServerId, computerServer.getId());
        opsDeployDao.delete(wrapperDeploy);

        // 绑定关系
        if (CollUtil.isNotEmpty(deployList)){
            List<String> deployIdList = deployList.stream().map(OpsDeploy::getId).collect(Collectors.toList());
            LambdaUpdateWrapper<OpsDeployLink> wrapperApp = new LambdaUpdateWrapper<>();
            wrapperApp.in(OpsDeployLink::getOpsDeployId, deployIdList);
            opsDeployLinkDao.delete(wrapperApp);
        }

        // todo 上面的图片都还没做处理

    }

    /**
     * 管理员- 查询全部的计算机
     * @param page 分页参数
     * @param query 查询参数
     * @return
     */
    public Page<OpsComputerServerVo> getAllComputerServerPageList(Page page, ComputerServerAllQo query) {
        return opsComputerServerDao.getAllComputerServerPageList(page, query);
    }

    /**
     * 获取可迁移的目标计算机
     * @param computerServerId 当前计算机
     * @param parentId 父级id
     * @return
     */
    public List<OpsComputerServerVo> getTransfer(String computerServerId, String parentId) {
        return opsComputerServerDao.getTransfer(computerServerId, parentId);
    }

    /**
     * 迁移数据用户到另外一个计算机下面
     * @param sonNodeList 子节点
     * @param server 当前计算机
     */
    @Transactional(rollbackFor = Exception.class)
    public void migrate(List<OpsComputerServerVo> sonNodeList, OpsComputerServer server) {
        opsComputerServerDao.updateById(server);
        if (CollUtil.isNotEmpty(sonNodeList)){
            for (OpsComputerServerVo opsComputerServerVo : sonNodeList) {
                opsComputerServerDao.updateById(opsComputerServerVo);
            }
        }
    }
}
